#ifndef __DEFINE__
#define __DEFINE__

#define STATIC static
#define INLINE inline
#define CONST const

typedef void VOID;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long long QWORD;
typedef long double TWORD;
typedef long LONG;
typedef unsigned long ULONG;
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;

#ifdef __amd64
typedef unsigned long DWORD32;
typedef unsigned long long DWORD;
#else
typedef unsigned long DWORD;
typedef unsigned int size_t;
#endif

typedef DWORD DWORD_PTR;

typedef int BOOL;
typedef unsigned char BOOLEAN;

#define TRUE 1
#define FALSE 0

typedef VOID *PVOID;
typedef BYTE *PBYTE;
typedef WORD *PWORD;
typedef DWORD *PDWORD;
typedef QWORD *PQWORD;
typedef TWORD *PTWORD;
typedef LONG *PLONG;
typedef ULONG *PULONG;
typedef LONGLONG *PLONGLONG;
typedef ULONGLONG *PULONGLONG;

typedef VOID *LPVOID;
typedef BYTE *LPBYTE;
typedef WORD *LPWORD;
typedef DWORD *LPDWORD;
typedef QWORD *LPQWORD;
typedef TWORD *LPTWORD;
typedef LONG *LPLONG;
typedef ULONG *LPULONG;
typedef LONGLONG *LPLONGLONG;
typedef ULONGLONG *LPULONGLONG;

typedef union LARGE_INTEGER {
    DWORD dwLow;
    LONG lHigh;
} *PLARGE_INTEGER, *LPLARGE_INTEGER;

typedef char CHAR;
typedef int WCHAR;
typedef int TCHAR;

typedef CHAR *LPSTR;
typedef char *LPCSTR;
typedef WCHAR *LPWSTR;
typedef WCHAR *LPCWSTR;
typedef TCHAR *LPTSTR;
typedef TCHAR *LPCTSTR;

typedef LPVOID HANDLE;

typedef HANDLE *PHANDLE;

typedef int INT;
typedef unsigned int UINT;

typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;

typedef BYTE SPINLOCK;

#define NULL (0)

#define READ_PORT_BYTE(port, var)                                              \
  __asm__("in %%dx,%%al" : "=a"(var) : "d"(port))
#define READ_PORT_WORD(port, var)                                              \
  __asm__("in %%dx,%%ax" : "=a"(var) : "d"(port))
#define READ_PORT_DWORD(port, var)                                             \
  __asm__("in %%dx,%%eax" : "=a"(var) : "d"(port))

#define WRITE_PORT_BYTE(port, var)                                             \
  __asm__("out %%al,%%dx" ::"a"(var), "d"(port))
#define WRITE_PORT_WORD(port, var)                                             \
  __asm__("out %%ax,%%dx" ::"a"(var), "d"(port))
#define WRITE_PORT_DWORD(port, var)                                            \
  __asm__("out %%eax,%%dx" ::"a"(var), "d"(port))

#define __CLI() __asm__("cli")
#define __STI() __asm__("sti")

#define __CLD() __asm__("cld")
#define __STD() __asm__("std")

#define __CLC() __asm__("clc")
#define __STC() __asm__("stc")
#define __CMC() __asm__("cmc")

#define __HALT() __asm__("hlt")

#define __LGDT(ptr) __asm__("lgdt (%0)" ::"r"(ptr))
#define __LLDT(ptr) __asm__("lldt (%0)" ::"r"(ptr))
#define __LIDT(ptr) __asm__("lidt (%0)" ::"r"(ptr))

#define __SGDT(ptr) __asm__("sgdt (%0)" ::"r"(ptr))
#define __SLDT(ptr) __asm__("sldt (%0)" ::"r"(ptr))
#define __SIDT(ptr) __asm__("sidt (%0)" ::"r"(ptr))

#define __set_cr0(var) __asm__("mov %%eax,%%cr0" ::"a"(var))
#define __set_cr1(var) __asm__("mov %%eax,%%cr1" ::"a"(var))
#define __set_cr2(var) __asm__("mov %%eax,%%cr2" ::"a"(var))
#define __set_cr3(var) __asm__("mov %%eax,%%cr3" ::"a"(var))
#define __set_cr4(var) __asm__("mov %%eax,%%cr4" ::"a"(var))

#define __get_cr0(var) __asm__("mov %%cr0,%%eax" : "=a"(var))
#define __get_cr1(var) __asm__("mov %%cr1,%%eax" : "=a"(var))
#define __get_cr2(var) __asm__("mov %%cr2,%%eax" : "=a"(var))
#define __get_cr3(var) __asm__("mov %%cr3,%%eax" : "=a"(var))
#define __get_cr4(var) __asm__("mov %%cr4,%%eax" : "=a"(var))

typedef char *va_list;
#define va_start(ap, v) (ap = (char *)&v)
#define va_end(ap) (ap = NULL)
#define va_arg(ap, t) *((t *)(ap += 4))

#define TOTAL_MEMORY_BYTES (*(DWORD *)(DWORD_PTR)0xc0000500)

#define __SYSCALL0(no) __asm__("int $0x80" ::"a"(no))
#define __SYSCALL1(no, a) __asm__("int $0x80" ::"a"(no), "b"(a))
#define __SYSCALL2(no, a, b) __asm__("int $0x80" ::"a"(no), "b"(a), "c"(b))
#define __SYSCALL3(no, a, b, c)                                                \
  __asm__("int $0x80" ::"a"(no), "b"(a), "c"(b), "d"(c))

#define __SYSCALL0R(no, ret) __asm__("int $0x80" : "=a"(ret) : "a"(no))
#define __SYSCALL1R(no, a, ret)                                                \
  __asm__("int $0x80" : "=a"(ret) : "a"(no), "b"(a))
#define __SYSCALL2R(no, a, b, ret)                                             \
  __asm__("int $0x80" : "=a"(ret) : "a"(no), "b"(a), "c"(b))
#define __SYSCALL3R(no, a, b, c, ret)                                          \
  __asm__("int $0x80" : "=a"(ret) : "a"(no), "b"(a), "c"(b), "d"(c))

void Panic(const LPSTR lpPanicMsg);

#endif